package com.ikun.admin.common.aspect;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.annotation.TableName;
import com.ikun.admin.common.annotation.OperationAnno;
import com.ikun.admin.common.constant.CommonConstant;
import com.ikun.admin.modules.auth.eneity.SecurityUser;
import com.ikun.admin.modules.auth.utils.SecurityUtil;
import com.ikun.admin.modules.sys.entity.LogOperation;
import com.ikun.admin.modules.sys.iservice.ILogService;
import com.ikun.common.utils.HttpContextUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.Objects;

/**
 * @ClassName Operation
 * @Description:
 * @CreateDate: 2024/4/11 10:10
 */
@Aspect
@Component
@Slf4j
public class OperationAspect {


    //    private static final Logger log = LoggerFactory.getLogger(OperationAspect.class);
    @Autowired
    private ILogService iLogService;

    @Autowired
    private SecurityUser currentLoginUser;

    @Pointcut("@annotation(com.ikun.admin.common.annotation.OperationAnno)")
    public void pointcut() {
    }

    @After("pointcut()")
    public void success(JoinPoint joinPoint) {
        this.saveLog(joinPoint, CommonConstant.ASPECT_STATUS_SUCCESS, null);
        log.info("记录一条操作日志，操作成功");
    }

    @AfterThrowing(pointcut = "pointcut()", throwing = "exception")
    public void fail(JoinPoint joinPoint, Throwable exception) {
        this.saveLog(joinPoint, CommonConstant.ASPECT_STATUS_SUCCESS, exception);
        log.info("记录一条操作日志，操作失败,异常信息为:{}", exception.getMessage());
    }

    private void saveLog(JoinPoint joinPoint, Integer status, Throwable exception) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        OperationAnno operationAnno = method.getAnnotation(OperationAnno.class);
        boolean open = operationAnno.open();
        if (!open) {
            return;
        }
        Class<? extends Serializable> tableEntity = operationAnno.tableEntity();
        String tableName = "";
        if (Objects.nonNull(tableEntity)) {
            TableName annotation = tableEntity.getAnnotation(TableName.class);
            tableName = Objects.nonNull(annotation) ? annotation.value() : "";
        }
        int type = operationAnno.type();

        LogOperation logOperation = new LogOperation();
        logOperation.setStatus(status);
        logOperation.setTableName(tableName);
        logOperation.setType(type);
        logOperation.setIp(HttpContextUtils.getIp());
        logOperation.setOperator(SecurityUtil.getCurrentUserId());
        logOperation.setRequestMethod(method.getName());
        logOperation.setRequestUri(HttpContextUtils.getRequestUri());
        joinPoint.getArgs();
        logOperation.setRequestParams(JSONObject.toJSONString(joinPoint.getArgs()));
        if (Objects.nonNull(exception)) {
            logOperation.setFailInfo(exception.getMessage());
        }
        iLogService.saveOperationLog(logOperation);
    }
}
